package com.arpa.oms.service.impl;

import cn.hutool.core.util.IdUtil;
import com.arpa.core.utils.collection.CollectionUtil;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.cache.ShipmentCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.OmsAutoCheckDTO;
import com.arpa.oms.domain.entity.OmsAutoCheck;
import com.arpa.oms.domain.entity.OmsAutoCheckGoods;
import com.arpa.oms.domain.enums.OmsUnpackRuleEnum;
import com.arpa.oms.mapper.OmsAutoCheckMapper;
import com.arpa.oms.service.IOmsAutoCheckGoodsService;
import com.arpa.oms.service.IOmsAutoCheckService;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.domain.consts.PropertyConst;
import com.arpa.wms.domain.enums.StatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 自动审核规则 服务实现类
 * </p>
 *
 * @author spb
 * @since 2021-07-24
 */
@Service
public class OmsAutoCheckServiceImpl extends ServiceImpl<OmsAutoCheckMapper, OmsAutoCheck> implements IOmsAutoCheckService {

    @Resource
    private PartyCache partyCache;
    @Resource
    private ShipmentCache shipmentCache;
    @Autowired
    private IOmsAutoCheckGoodsService iOmsAutoCheckGoodsService;

    @Autowired
    private GoodsCache goodsCache;

    @Override
    public Integer listCount(OmsAutoCheckDTO autoCheckDTO) {
        LambdaQueryWrapper<OmsAutoCheck> queryWrapper = getQueryWrapper(new QueryWrapper<OmsAutoCheck>(), autoCheckDTO);
        Integer count = baseMapper.selectCount(queryWrapper);
        return count;
    }

    @Override
    public List<OmsAutoCheck> listPage(OmsAutoCheckDTO autoCheckDTO) {
        QueryWrapper<OmsAutoCheck> query = new QueryWrapper<OmsAutoCheck>();
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotBlank(autoCheckDTO.getSortField())) {
            autoCheckDTO.setSortField(CommonUtil.camel2Underline(autoCheckDTO.getSortField()));
            if (StringUtils.isNotBlank(autoCheckDTO.getSortType()) && autoCheckDTO.getSortType().toLowerCase().equals("asc")) {
                query.orderByAsc(autoCheckDTO.getSortField());
            } else {
                query.orderByDesc(autoCheckDTO.getSortField());
            }
        } else {
            query.orderByDesc("gmt_created");
        }
        LambdaQueryWrapper<OmsAutoCheck> queryWrapper = getQueryWrapper(query, autoCheckDTO);
        int start = (autoCheckDTO.getPageNum()-1)*autoCheckDTO.getPageSize();
        queryWrapper.last("limit " + start + " , " + autoCheckDTO.getPageSize());
        List<OmsAutoCheck> list = baseMapper.selectList(queryWrapper);
        return list;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(OmsAutoCheck entity) {
        entity.setCode(IdUtil.simpleUUID());
        entity.setCreatedBy(UserUtil.getCode());
        entity.setModifiedBy(UserUtil.getCode());
        String loginName = partyCache.translate(UserUtil.getCode());
        entity.setCreatedName(loginName);
        entity.setModifiedName(loginName);
        entity.setStatus(StatusEnum.UNACTIVE.getValue());
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        int num = baseMapper.insert(entity);
        if (num <= 0) {
            return false;
        }
        if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
            List<String> goodsList = entity.getGoodsCode();
            if (CollectionUtil.isNotEmpty(goodsList)) {
                List<OmsAutoCheckGoods> checkGoodsList = new ArrayList<>();
                for (String goodCode : goodsList) {
                    OmsAutoCheckGoods omsAutoCheckGoods = new OmsAutoCheckGoods();
                    omsAutoCheckGoods.setGoodsCode(goodCode);
                    omsAutoCheckGoods.setGoodsName(goodsCache.translate(goodCode));
                    omsAutoCheckGoods.setAuthCheckCode(entity.getCode());
                    omsAutoCheckGoods.setCode(IdUtil.simpleUUID());
                    omsAutoCheckGoods.setCreatedBy(UserUtil.getCode());
                    omsAutoCheckGoods.setModifiedBy(UserUtil.getCode());
                    omsAutoCheckGoods.setCreatedName(loginName);
                    omsAutoCheckGoods.setModifiedName(loginName);
                    checkGoodsList.add(omsAutoCheckGoods);
                }
                iOmsAutoCheckGoodsService.saveBatch(checkGoodsList);
                return true;
            } else {
                throw new ServiceException("指定特定商品，商品列表不能为空");
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateByCode(OmsAutoCheck entity) {
        if (entity.getEndTime() != null) {
            LocalDateTime endTime = entity.getEndTime().plusSeconds(86399);
            entity.setEndTime(endTime);
        }
        entity.setModifiedBy(UserUtil.getCode());
        String loginName = partyCache.translate(UserUtil.getCode());
        entity.setModifiedName(loginName);
        entity.setStatus(StatusEnum.UNACTIVE.getValue());
        entity.setShipmentName(shipmentCache.translate(entity.getShipmentCode()));
        Integer num = baseMapper.update(entity, new QueryWrapper<OmsAutoCheck>().lambda().eq(OmsAutoCheck::getCode, entity.getCode()));
        if (num <= 0) {
            return false;
        }
        iOmsAutoCheckGoodsService.remove(new QueryWrapper<OmsAutoCheckGoods>().lambda().eq(OmsAutoCheckGoods::getAuthCheckCode, entity.getCode()));
        if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(entity.getAllGoods())) {
            List<String> goodsList = entity.getGoodsCode();
            if (CollectionUtil.isEmpty(goodsList)) {
                throw new ServiceException("指定特定商品，商品列表不能为空");
            }
            List<OmsAutoCheckGoods> checkGoodsList = new ArrayList<>();
            for (String goodCode : goodsList) {
                OmsAutoCheckGoods omsAutoCheckGoods = new OmsAutoCheckGoods();
                omsAutoCheckGoods.setGoodsCode(goodCode);
                omsAutoCheckGoods.setGoodsName(goodsCache.translate(goodCode));
                omsAutoCheckGoods.setAuthCheckCode(entity.getCode());
                omsAutoCheckGoods.setCode(IdUtil.simpleUUID());
                omsAutoCheckGoods.setCreatedBy(UserUtil.getCode());
                omsAutoCheckGoods.setModifiedBy(UserUtil.getCode());
                omsAutoCheckGoods.setCreatedName(loginName);
                omsAutoCheckGoods.setModifiedName(loginName);
                checkGoodsList.add(omsAutoCheckGoods);
            }
            iOmsAutoCheckGoodsService.saveBatch(checkGoodsList);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean batchUpdateStatus(String code, String value) {
        Map<String, Integer> resultData = new HashMap<>();
        resultData.put(PropertyConst.SUCCESS, 0);
        // 待生效规则
        OmsAutoCheck autoCheck = baseMapper.selectOne(new QueryWrapper<OmsAutoCheck>().lambda().eq(OmsAutoCheck::getCode, code));
        if (StatusEnum.ACTIVE.getValue().equals(value)) {
            // 已生效规则
            List<OmsAutoCheck> activeList = baseMapper.selectList(new QueryWrapper<OmsAutoCheck>().lambda().eq(OmsAutoCheck::getShipmentCode, UserUtil.getLoginWarehouseCodeOrShipmentCode()).eq(OmsAutoCheck::getStatus, StatusEnum.ACTIVE.getValue()));
            if (null == autoCheck) {
                throw new ServiceException("未查询到可启用数据");
            }
            if (CollectionUtil.isNotEmpty(activeList)) {
                for (OmsAutoCheck check : activeList) {
                    if (compareTwoTime(autoCheck.getStartTime(), autoCheck.getEndTime(), check.getStartTime(), check.getEndTime())) {
                        throw new ServiceException("生效时间内已存在一条启用规则【" + check.getName() + "】");
                    }
                }
            }
        }
        autoCheck.setStatus(value);
        return updateById(autoCheck);
    }

    @Override
    public Map<String, Integer> deleteByCodes(List<String> codes) {
        Integer num = baseMapper.delete(new QueryWrapper<OmsAutoCheck>().lambda().in(OmsAutoCheck::getCode, codes));
        if (num > 0) {
            iOmsAutoCheckGoodsService.remove(new QueryWrapper<OmsAutoCheckGoods>().lambda().in(OmsAutoCheckGoods::getAuthCheckCode, codes));
        }
        Map<String, Integer> resultData = new HashMap<>();
        resultData.put(PropertyConst.SUCCESS, num);
        return resultData;
    }

    @Override
    public OmsAutoCheck getDetailInfoByCode(String code) {
        OmsAutoCheck autoCheck = baseMapper.selectOne(new QueryWrapper<OmsAutoCheck>().lambda().eq(OmsAutoCheck::getCode, code));
        if (OmsUnpackRuleEnum.PART_GOODS.getValue().equals(autoCheck.getAllGoods())) {
            List<OmsAutoCheckGoods> list = iOmsAutoCheckGoodsService.list(new QueryWrapper<OmsAutoCheckGoods>().lambda().eq(OmsAutoCheckGoods::getAuthCheckCode, code).orderByAsc(OmsAutoCheckGoods::getId));
            autoCheck.setGoodsCode(list.stream().map(v ->v.getGoodsCode()).collect(Collectors.toList()));
        }
        return autoCheck;
    }

    private LambdaQueryWrapper<OmsAutoCheck> getQueryWrapper(QueryWrapper query, OmsAutoCheckDTO autoCheckDTO) {
        LambdaQueryWrapper<OmsAutoCheck> queryWrapper = query.lambda();
        if (StringUtils.isNotBlank(autoCheckDTO.getStatus())) {
            queryWrapper.eq(OmsAutoCheck::getStatus, autoCheckDTO.getStatus());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getShipmentCode())) {
            queryWrapper.eq(OmsAutoCheck::getShipmentCode, autoCheckDTO.getShipmentCode());
        } else {
            queryWrapper.eq(OmsAutoCheck::getShipmentCode, UserUtil.getLoginWarehouseCodeOrShipmentCode());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getModifiedBy())) {
            queryWrapper.eq(OmsAutoCheck::getModifiedBy, autoCheckDTO.getModifiedBy());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getCreatedBy())) {
            queryWrapper.eq(OmsAutoCheck::getCreatedBy, autoCheckDTO.getCreatedBy());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getCreatedName())) {
            queryWrapper.like(OmsAutoCheck::getCreatedName, autoCheckDTO.getCreatedName());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getShopCode())) {
            queryWrapper.eq(OmsAutoCheck::getShopCode, autoCheckDTO.getShopCode());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getShopName())) {
            queryWrapper.like(OmsAutoCheck::getShopName, autoCheckDTO.getShopName());
        }

        if (StringUtils.isNotBlank(autoCheckDTO.getModifiedName())) {
            queryWrapper.like(OmsAutoCheck::getModifiedName, autoCheckDTO.getModifiedName());
        }

        if ((null != autoCheckDTO.getGmtCreatedStart()) && (null != autoCheckDTO.getGmtCreatedEnd())) {
            queryWrapper.between(OmsAutoCheck::getGmtCreated, autoCheckDTO.getGmtCreatedStart(), autoCheckDTO.getGmtCreatedEnd());
        } else {
            if (null != autoCheckDTO.getGmtCreatedStart()) {
                queryWrapper.ge(OmsAutoCheck::getGmtCreated, autoCheckDTO.getGmtCreatedStart());
            }
            if (null != autoCheckDTO.getGmtCreatedEnd()) {
                queryWrapper.le(OmsAutoCheck::getGmtCreated, autoCheckDTO.getGmtCreatedEnd());
            }
        }

        if ((null != autoCheckDTO.getGmtModifiedStart()) && (null != autoCheckDTO.getGmtModifiedEnd())) {
            queryWrapper.between(OmsAutoCheck::getGmtCreated, autoCheckDTO.getGmtModifiedStart(), autoCheckDTO.getGmtModifiedEnd());
        } else {
            if (null != autoCheckDTO.getGmtModifiedStart()) {
                queryWrapper.ge(OmsAutoCheck::getGmtModified, autoCheckDTO.getGmtModifiedStart());
            }
            if (null != autoCheckDTO.getGmtModifiedEnd()) {
                queryWrapper.le(OmsAutoCheck::getGmtModified, autoCheckDTO.getGmtModifiedEnd());
            }
        }

        if (StringUtils.isNotBlank(autoCheckDTO.getName())) {
            queryWrapper.like(OmsAutoCheck::getName, autoCheckDTO.getName());
        }
        if (StringUtils.isNotBlank(autoCheckDTO.getRemark())) {
            queryWrapper.like(OmsAutoCheck::getRemark, autoCheckDTO.getRemark());
        }
        return queryWrapper;
    }

    /**
     * 判断时间是否重叠
     * @param startOne
     * @param endOne
     * @param startTwo
     * @param endTwo
     * @return
     */
    private static Boolean compareTwoTime(LocalDateTime startOne, LocalDateTime endOne, LocalDateTime startTwo, LocalDateTime endTwo){
        //after 当start1小于等于end2时返回flase  before end1大于等于start2返回flase
        if ((!startOne.isAfter(endTwo))&&(!endOne.isBefore(startTwo))){
            System.out.println("时间重叠");
            //时间重叠
            return true;
        }
        System.out.println("时间不重叠");
        //时间不重叠
        return false;
    }
}
